package server

import (
	"fmt"
	"my_im2/server/_interface"
	"my_im2/server/module"
)

type Server struct {
	communicator _interface.Communicator
	logger       _interface.Logger
	business     _interface.Business
	db           _interface.Db
}

func NewServer(ip string, port int) *Server {
	srv := &Server{}

	cm := module.NewCommunicationModule(ip, port, srv)
	srv.communicator = cm

	srv.logger = module.NewLogModule()

	bm := module.NewBusinessModule(srv)
	srv.business = bm

	dm := module.NewDbModule(srv)
	srv.db = dm

	return srv
}

func (srv *Server) Start() {
	srv.communicator.Start()
}

func (srv *Server) SendMsgToId(id uint, msg string) {
	srv.communicator.SendMsg(id, msg)
}

func (srv *Server) SendMsgToUser(user string, msg string) {
	if id, ok := srv.db.GetConnId(user); ok {
		srv.communicator.SendMsg(id, msg)
	}
}

func (srv *Server) SendMsgToGroup(group string, msg string) {
	members := srv.db.GetGroupMembers(group)
	for _, user := range members {
		srv.SendMsgToUser(user, msg)
	}
}

func (srv *Server) OnDisconnect(id uint) {
	//判断是否登录
	if me, ok := srv.db.GetConnUser(id); ok {
		//执行下线
		srv.db.ConnDisconnect(id)
		//通知好友下线
		srv.NotifyFriendOffline(me)
	}
}

func (srv *Server) NotifyFriendOnline(friend string) {
	msg := fmt.Sprintf("notifyfriendonline|%s", friend)
	//找出所有用户（friend是这些用户的好友）
	users := srv.db.GetUsersWhoHasFriend(friend)
	for _, u := range users {
		//拿到用户的conn
		if id, ok := srv.db.GetConnId(u); ok {
			srv.SendMsgToId(id, msg)
		}
	}
}

func (srv *Server) NotifyFriendOffline(friend string) {
	msg := fmt.Sprintf("notifyfriendoffline|%s", friend)
	//找出所有用户（friend是这些用户的好友）
	users := srv.db.GetUsersWhoHasFriend(friend)
	for _, u := range users {
		//拿到用户的conn
		if id, ok := srv.db.GetConnId(u); ok {
			srv.SendMsgToId(id, msg)
		}
	}
}

func (srv *Server) GetLogger() _interface.Logger {
	return srv.logger
}

func (srv *Server) GetCommunicator() _interface.Communicator {
	return srv.communicator
}

func (srv *Server) GetBusiness() _interface.Business {
	return srv.business
}

func (srv *Server) GetDb() _interface.Db {
	return srv.db
}
